#include <errno.h>

#include <string>
#include <sstream>

#include <pwd.h>

#include "system.h"
#include "procsys.h"
#include "utils.h"

using namespace std;

time_t get_boot_time()
{
    SysStatFileContent s;
    s.loadFromSys();

    istringstream ss(s.btime);
    time_t res;
    ss >> res;

    return res;
}

System::System()
{
    m_boot_time = get_boot_time();
    m_filecontent_cpuinfo.loadFromSys();

    _load_user_names();
}

time_t System::getBootTime() const
{
    return m_boot_time;
}

jiffies_t System::getTotalCpuTime() const
{
    SysStatFileContent stat;
    stat.loadFromSys();

    istringstream ss(stat.cpu);

    jiffies_t user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice;

    ss >> user >> nice >> system >> idle >> iowait >> irq >> softirq >> steal >> guest >> guest_nice;

    return user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice;
}

int System::getCpuCount() const
{
    return (int) m_filecontent_cpuinfo.vec.size();
}

jiffies_t System::getTotalCpuTimeOf(int cpuIndex) const
{
    SysStatFileContent stat;
    stat.loadFromSys();

    istringstream ss(stat.cpuN[cpuIndex]);

    jiffies_t user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice;

    ss >> user >> nice >> system >> idle >> iowait >> irq >> softirq >> steal >> guest >> guest_nice;

    return user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice;
}

jiffies_t System::getJiffies() const
{
    return getTotalCpuTimeOf(0);
}

std::string System::getUserName(uid_t uid) const
{
    return m_usernames.find(uid)->second;
}

void System::_load_user_names()
{
    /*
    getpwent()为非线程安全函数，这里使用是因为System类作为常量在程序启动时就完成初始化。
    */

    errno = 0;

    passwd *p = NULL;

again:
    while ((p = getpwent()) != NULL) {
        string s = p->pw_name;
        m_usernames[p->pw_uid] = s;
    }

    if (errno == EINTR) {
        goto again;
    }

    endpwent();
}
